package org.geektimes.projects.user.web.repository;

import org.geektimes.projects.user.domain.User;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.sql.*;
import java.util.Collection;

public class DerbyUserRepository implements UserRepository{
    public final String CREATE_USERS_TABLE_DDL_SQL = "CREATE TABLE users(" +
            "id INT NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1), " +
            "name VARCHAR(16) NOT NULL, " +
            "password VARCHAR(64) NOT NULL, " +
            "email VARCHAR(64) NOT NULL, " +
            "phoneNumber VARCHAR(64) NOT NULL" +
            ")";

    private String databaseURL = "jdbc:derby:/Users/00418053/develop/Derby/db-derby-10.14.2.0-bin/user-platform;create=true";

    private String INSERT_USER_DML_SQL = "INSERT INTO users(name,password,email,phoneNumber) VALUES ('%s','%s','%s','%s')";

    @Override
    public boolean save(User user){

        try{
            Connection connection = DriverManager.getConnection(databaseURL);
        Statement statement = connection.createStatement();

        System.out.println("sql:"+String.format(INSERT_USER_DML_SQL,user.getName(),user.getPassword(),user.getEmail(),user.getPhoneNumber()));
        statement.execute(CREATE_USERS_TABLE_DDL_SQL);
        System.out.println(statement.executeUpdate(String.format(INSERT_USER_DML_SQL,user.getName(),user.getPassword(),user.getEmail(),user.getPhoneNumber())));  // 5

        // 执行查询语句（DML）
        ResultSet resultSet = statement.executeQuery("SELECT id,name,password,email,phoneNumber FROM users");

        // BeanInfo
        BeanInfo userBeanInfo = Introspector.getBeanInfo(User.class, Object.class);
        // 所有的 Properties 信息
        for (PropertyDescriptor propertyDescriptor : userBeanInfo.getPropertyDescriptors()) {
            System.out.println(propertyDescriptor.getName() + " , " + propertyDescriptor.getPropertyType());
        }
            // 写一个简单的 ORM 框架
            while (resultSet.next()) { // 如果存在并且游标滚动
                User user1 = new User();

                // ResultSetMetaData 元信息


                ResultSetMetaData metaData = resultSet.getMetaData();
                System.out.println("当前表的名称：" + metaData.getTableName(1));
                System.out.println("当前表的列个数：" + metaData.getColumnCount());
                for (int i = 1; i <= metaData.getColumnCount(); i++) {
                    System.out.println("列名称：" + metaData.getColumnLabel(i) + ", 类型：" + metaData.getColumnClassName(i));
                }

                StringBuilder queryAllUsersSQLBuilder = new StringBuilder("SELECT");
                for (int i = 1; i <= metaData.getColumnCount(); i++) {
                    queryAllUsersSQLBuilder.append(" ").append(metaData.getColumnLabel(i)).append(",");
                }
                // 移除最后一个 ","
                queryAllUsersSQLBuilder.deleteCharAt(queryAllUsersSQLBuilder.length() - 1);
                queryAllUsersSQLBuilder.append(" FROM ").append(metaData.getTableName(1));

                System.out.println(queryAllUsersSQLBuilder);

                // 方法直接调用（编译时，生成字节码）
//            user.setId(resultSet.getLong("id"));
//            user.setName(resultSet.getString("name"));
//            user.setPassword(resultSet.getString("password"));
//            user.setEmail(resultSet.getString("email"));
//            user.setPhoneNumber(resultSet.getString("phoneNumber"));

                // 利用反射 API，来实现字节码提升

                // User 类是通过配置文件，类名成
                // ClassLoader.loadClass -> Class.newInstance()
                // ORM 映射核心思想：通过反射执行代码（性能相对开销大）
                for (PropertyDescriptor propertyDescriptor : userBeanInfo.getPropertyDescriptors()) {
                    String fieldName = propertyDescriptor.getName();
                    Class fieldType = propertyDescriptor.getPropertyType();

                    // 获取 User 类 Setter方法
                    // PropertyDescriptor ReadMethod 等于 Getter 方法
                    // PropertyDescriptor WriteMethod 等于 Setter 方法
                    Method setterMethodFromUser = propertyDescriptor.getWriteMethod();
                }

                System.out.println(user);
            }
            connection.close();
        }catch(SQLException e){
            e.printStackTrace();
            System.out.println(e.getMessage());
        } catch (IntrospectionException e) {
            e.printStackTrace();
        }finally {

        }

        return false;
    }

    @Override
    public boolean deleteById(Long userId) {
        return false;
    }

    @Override
    public boolean update(User user) {
        return false;
    }

    @Override
    public User getById(Long userId) {
        return null;
    }

    @Override
    public User getByNameAndPassword(String userName, String password) {
        return null;
    }

    @Override
    public Collection<User> getAll() {
        return null;
    }
}
